package task

import (
	"sync"
	"sync/atomic"
	"time"
)

const (
	globalName = "global"
)

var (
	globalInstance = atomic.Pointer[TaskManager]{}
	globalOnce     sync.Once
)

// GetGlobal 获取全局默认任务管理器
func GetGlobal() *TaskManager {
	// 初始化全局任务管理器
	globalOnce.Do(func() {
		if globalInstance.Load() == nil {
			tm := NewTaskManager(globalName, &defaultOptions)
			tm.isGlobal = true
			globalInstance.Store(tm)
		}
	})
	return globalInstance.Load()
}

// SetGlobal 设置全局默认任务管理器
func SetGlobal(tm *TaskManager) {
	if tm != nil {
		c := *tm
		c.isGlobal = true
		globalInstance.Store(&c)
	}
}

// OnceAt 创建一次性定时任务（基于一个明确时间）
//   - executeAt 调度器内部会统一转换为本地时区后处理，如已过期则调整为当前时间(立即执行)
//   - ops 可通过 TaskOption 指定任务运行的超时时间: WithTimeout
//   - 注意：任务添加后/执行前相同Key任务的添加操作会直接覆盖前一次添加的任务
func OnceAt(key string, executeAt time.Time, handler TaskHandler, ops ...TaskOption) error {
	return GetGlobal().OnceAt(key, executeAt, handler, ops...)
}

// OnceAfter 创建一次性延迟任务（基于一个延迟时间）
//   - ops 可通过 TaskOption 指定任务运行的开始时间: WithStartAt  超时时间: WithTimeout 等
//   - 注意：任务添加后/执行前相同Key任务的添加操作会直接覆盖前一次添加的任务
func OnceAfter(key string, delay time.Duration, handler TaskHandler, ops ...TaskOption) error {
	return GetGlobal().OnceAfter(key, delay, handler, ops...)
}

// OnceBuffer 创建一次性延迟任务(缓冲模式), 常用于延迟更新任务, 如缓存更新等场景
//   - ops 可通过 TaskOption 指定任务运行的开始时间: WithStartAt  超时时间: WithTimeout 等
//   - 注意：任务添加后/执行前相同Key任务的添加操作将会忽略
func OnceBuffer(key string, delay time.Duration, handler TaskHandler, ops ...TaskOption) error {
	return GetGlobal().OnceBuffer(key, delay, handler, ops...)
}

// EveryInterval 创建周期性任务,基于一个明确的间隔时间 interval
//   - ops 可通过 TaskOption 指定具体的具体运行时刻：WithHour WithMinute WithSecond WithMillisecond
//   - 注意：任务添加后/执行前相同Key任务的添加操作会直接覆盖前一次添加的任务
func EveryInterval(key string, interval time.Duration, handler TaskHandler, ops ...TaskOption) error {
	return GetGlobal().EveryInterval(key, interval, handler, ops...)
}

// EverySecond 创建周期性任务（每几秒钟运行一次）
//   - ops 可通过 TaskOption 指定具体的具体运行时刻: WithMillisecond
//   - 注意：任务添加后/执行前相同Key任务的添加操作会直接覆盖前一次添加的任务
func EverySecond(key string, seconds int, handler TaskHandler, ops ...TaskOption) error {
	return GetGlobal().EverySecond(key, seconds, handler, ops...)
}

// EveryMinute 创建周期性任务（每几分钟运行一次）
//   - ops 可通过 TaskOption 指定具体的具体运行时刻：WithSecond WithMillisecond
//   - 注意：任务添加后/执行前相同Key任务的添加操作会直接覆盖前一次添加的任务
func EveryMinute(key string, minutes int, handler TaskHandler, ops ...TaskOption) error {
	return GetGlobal().EveryMinute(key, minutes, handler, ops...)
}

// EveryHour 创建周期性任务（每几小时运行一次）
//   - ops 可通过 TaskOption 指定具体的具体运行时刻：WithMinute WithSecond WithMillisecond
//   - 注意：任务添加后/执行前相同Key任务的添加操作会直接覆盖前一次添加的任务
func EveryHour(key string, hours int, handler TaskHandler, ops ...TaskOption) error {
	return GetGlobal().EveryHour(key, hours, handler, ops...)
}

// EveryDay 创建周期性任务（每几天运行一次）
//   - ops 可通过 TaskOption 指定具体的具体运行时刻：WithHour WithMinute WithSecond WithMillisecond
//   - 注意：任务添加后/执行前相同Key任务的添加操作会直接覆盖前一次添加的任务
func EveryDay(key string, days int, handler TaskHandler, ops ...TaskOption) error {
	return GetGlobal().EveryDay(key, days, handler, ops...)
}

// EveryWeekDay 创建周期性任务（每周X运行一次）
//   - weekDay 0-7, 0/7 => 星期日
//   - ops 可通过 TaskOption 指定具体的具体运行时刻：WithHour WithMinute WithSecond WithMillisecond
//   - 注意：任务添加后/执行前相同Key任务的添加操作会直接覆盖前一次添加的任务
func EveryWeekDay(key string, weekDay int, handler TaskHandler, ops ...TaskOption) error {
	return GetGlobal().EveryWeekDay(key, weekDay, handler, ops...)
}

// EveryMonthDay 创建周期性任务（每月的某一日运行一次）
//   - day: 1-31, 如指定31号，但当月只有30天，则30日执行
//   - ops 可通过 TaskOption 指定具体的具体运行时刻：WithHour WithMinute WithSecond WithMillisecond
//   - 注意：任务添加后/执行前相同Key任务的添加操作会直接覆盖前一次添加的任务
func EveryMonthDay(key string, day int, handler TaskHandler, ops ...TaskOption) error {
	return GetGlobal().EveryMonthDay(key, day, handler, ops...)
}

// EveryMonthFirstDay 创建周期性任务（每月第1天运行一次）
//   - ops 可通过 TaskOption 指定具体的具体运行时刻：WithHour WithMinute WithSecond WithMillisecond
//   - 注意：任务添加后/执行前相同Key任务的添加操作会直接覆盖前一次添加的任务
func EveryMonthFirstDay(key string, handler TaskHandler, ops ...TaskOption) error {
	return GetGlobal().EveryMonthFirstDay(key, handler, ops...)
}

// EveryMonthLastDay 创建周期性任务（每月最后一天运行一次）
//   - ops 可通过 TaskOption 指定具体的具体运行时刻：WithHour WithMinute WithSecond WithMillisecond
//   - 注意：任务添加后/执行前相同Key任务的添加操作会直接覆盖前一次添加的任务
func EveryMonthLastDay(key string, handler TaskHandler, ops ...TaskOption) error {
	return GetGlobal().EveryMonthLastDay(key, handler, ops...)
}

// RemoveTask 删除指定key的任务
func RemoveTask(keys ...string) error {
	return GetGlobal().RemoveTask(keys...)
}

// RemoveTask 删除所有任务
func RemoveAllTasks() error {
	return GetGlobal().RemoveAllTasks()
}

// GetTask 获取指定key的定时任务信息
func GetTask(key string) (TaskInfo, error) {
	return GetGlobal().GetTask(key)
}

// GetAllTasks 获取所有定时任务
func GetAllTasks() []TaskInfo {
	return GetGlobal().GetAllTasks()
}

// Size 获取定时任务数量(包含未运行、已运行的全部任务)
//   - 包含全部定时任务的映射(可主动通过RemoveTask删除指定任务信息)
func Size() int {
	return GetGlobal().Size()
}

// IsRuning 获取定时任务队列运行状态
func IsRuning() bool {
	return GetGlobal().IsRuning()
}

// Monitor 获取任务运行监控信息
func Monitor() TaskMonitorData {
	return GetGlobal().Monitor()
}

// Stop 关闭定时任务管理器
//   - 注意：仅停止定时任务管理器的运行，不会删除任务数据
func Stop() {
	GetGlobal().Stop()
}

// Restart 重启定时任务管理器
//   - 注意：重启后，队列中如有任务，所有到期任务会立即运行
func Restart() {
	GetGlobal().Restart()
}
